// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

const {ccclass, property} = cc._decorator;

cc.macro.CLEANUP_IMAGE_CACHE = false;
cc.dynamicAtlasManager.enabled = true;

@ccclass
export default class NewClass extends cc.Component {

    // 热更界面
    @property(cc.Label)
    progress: cc.Label = null;
    @property(cc.Label)
    filesprogress: cc.Label = null;
    @property(cc.Sprite)
    tagimg: cc.Sprite = null;
    @property(cc.ProgressBar)
    progressbar: cc.ProgressBar = null;

    // 热更确认框
    @property(cc.Node)
    confirmlayer: cc.Node = null;  
    @property(cc.RichText)
    content: cc.RichText = null;  
    @property(cc.Button)
    sureButton: cc.Button = null;  
    @property(cc.Button)
    cancelButton: cc.Button = null;  

    // 热更文件
    @property(cc.Asset)
    manifestUrl : cc.Asset = null; 
    @property(Number)
    maxtryNum : Number = 2; 

    _checkListener: any;
    _updateListener: any;
    _am: jsb.AssetsManager = null;
    _updating: boolean = false;
    _canRetry: boolean = false;
    _storagePath: string = '';
    versionCompareHandle : any;
    _failCount : number = 0;
    
    onLoad () {
        if (!cc.sys.isNative) {
            return this.enter();
        }
        this._storagePath = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'hotupdate');
        cc.log('热更新路径 : ' + this._storagePath);

        // 版本号比较函数
        this.versionCompareHandle = function (versionA:string, versionB:string) {
            cc.log("自定义版本对比函数: version A is " + versionA + ', version B is ' + versionB);
            var vA = versionA.split('.');
            var vB = versionB.split('.');
            for (var i = 0; i < vA.length; ++i) {
                var a = parseInt(vA[i]);
                var b = parseInt(vB[i] || 0);
                if (a === b) {
                    continue;
                }
                else {
                    return a - b;
                }
            }
            if (vB.length > vA.length) {
                return -1;
            }
            else {
                return 0;
            }
        };

        this._am = new jsb.AssetsManager('', this._storagePath, this.versionCompareHandle);

        // 检查下载的文件的MD5是否一致
        /*this._am.setVerifyCallback(function (path:string, asset:any) {
            var md5 = calculateMD5(path);
            if (md5 === asset.md5)
                return true;
            else 
                return false;
        }.bind(this));*/

        this.progress.string = '检查服务器版本...';

        if (cc.sys.os === cc.sys.OS_ANDROID) {
            this._am.setMaxConcurrentTask(2);
        }
        
        this.filesprogress.string = '';
        this.progressbar.progress = 0;

        this.checkUpdate();
    }

    checkCb (event:any) {
        cc.log('Code: ' + event.getEventCode());
        let fail = false;
        let needUpdate = false;
        switch (event.getEventCode())
        {
            case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
                this.progress.string = "本地没有manifest文件.";
                break;
            case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
                fail = true;
                this.progress.string = "下载manifest文件失败.";
                break;
            case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
                fail = true;
                this.progress.string = "manifest文件格式有误.";
                break;
            case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
                this.progress.string = "已经是最新版本.";
                /*if(event.getAssetId() == "@remove_local"){
                    return this.restart();
                    
                }else*/
                // return this.restart();
                // this.restart();
                this.enter();
                break;
            case jsb.EventAssetsManager.NEW_VERSION_FOUND:
                this.progress.string = '找到新版本.';
                this.progressbar.progress = 0;
                needUpdate = true;
                break;
            case jsb.EventAssetsManager.LOCAL_VERSION_OUT_OF_DATE:
                this.progress.string = '当前版本太老.';
                this.progressbar.progress = 100;
                this.showConfirmLayer('当前版本太老需要更新到最新版本才能进入游戏！',this.end,this.end);
                break;
            default:
                return;
        }
        if(fail){
            this.showConfirmLayer('更新失败是否重试？',this.onSureFailButtonClick,this.onCancelFailButtonClick);
        }
        this._am.setEventCallback(null);
        this._checkListener = null;
        this._updating = false;
        if(needUpdate){
            this.hotUpdate();
        }
    }

    updateCb (event) {
        var needRestart = false;
        var failed = false;
        switch (event.getEventCode())
        {
            case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
                this.progress.string = "本地没有manifest文件.";
                failed = true;
                break;
            case jsb.EventAssetsManager.UPDATE_PROGRESSION:
                this.progressbar.progress = event.getPercent();
                this.progress.string = '版本更新中...'+(event.getPercent()*100).toFixed(2)+'%';
                let downsize = event.getDownloadedBytes();
                let totalsize = event.getTotalBytes();
                
                cc.log("进度----->"+downsize+"/"+totalsize);
                let danwei = '',danwei2 = '';
                if(downsize > 1024 * 1024){
                    downsize = (downsize/1024/1024).toFixed(2);
                    danwei =  "M";
                }else{
                    downsize = Math.ceil(downsize/1024);
                    danwei = "KB";
                }
                if(totalsize > 1024 * 1024){
                    totalsize = (totalsize/1024/1024).toFixed(2);
                    danwei2 =  "M";
                }else{
                    totalsize = Math.ceil(totalsize/1024);
                    danwei2 = "KB";
                }
                this.filesprogress.string = downsize+danwei+"/"+totalsize+danwei2+" "+"（"+event.getDownloadedFiles()+"/"+event.getTotalFiles()+"）";
                this.tagimg.node.x = -this.progressbar.totalLength/2+this.progressbar.totalLength*(this.progressbar.progress);
                var msg = event.getMessage();
                if (msg) {
                    //this.panel.info.string = 'Updated file: ' + msg;
                    // cc.log(event.getPercent()/100 + '% : ' + msg);
                }
                break;
            case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
                this.progress.string = "下载manifest文件失败.";
                break;
            case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
                this.progress.string = "manifest文件格式有误.";
                failed = true;
                break;
            case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
                this.progress.string = "已经是最新版本.";
                this.progressbar.progress = 1;
                failed = true;
                // this.restart();
                this.enter();
                break;
            case jsb.EventAssetsManager.UPDATE_FINISHED:
                this.progress.string = "更新完成.";
                needRestart = true;
                break;
            case jsb.EventAssetsManager.UPDATE_FAILED:
                this.progress.string = "更新失败."+event.getMessage();
                this._updating = false;
                this._canRetry = true;
                this.showConfirmLayer('有部分文件更新失败是否重试？',this.onSureTryButtonClick,this.onCancelTryButtonClick);
                break;
            case jsb.EventAssetsManager.ERROR_UPDATING:
                this.progress.string = "文件更新失败："+ event.getAssetId() + ', ' + event.getMessage();
                break;
            case jsb.EventAssetsManager.ERROR_DECOMPRESS:
                this.progress.string = "文件解压失败："+ event.getMessage();
                break;
            default:
                break;
        }

        if (failed) {
            this._am.setEventCallback(null);
            this._updateListener = null;
            this._updating = false;
        }

        if (needRestart) {
            this._am.setEventCallback(null);
            this._updateListener = null;
            // Prepend the manifest's search path
            var searchPaths = jsb.fileUtils.getSearchPaths();
            var newPaths = this._am.getLocalManifest().getSearchPaths();
            console.log(JSON.stringify(newPaths));
            Array.prototype.unshift.apply(searchPaths, newPaths);
            // This value will be retrieved and appended to the default search path during game startup,
            // please refer to samples/js-tests/main.js for detailed usage.
            // !!! Re-add the search paths in main.js is very important, otherwise, new scripts won't take effect.
            cc.sys.localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths));
            jsb.fileUtils.setSearchPaths(searchPaths);
            cc.log('---------------------------------------------------------重启游戏');
            this.progress.string = '请重启游戏';
            // this.restart();

            // cc.director.loadScene('hotUpdate');
        }
    }

    /*loadCustomManifest () {
        if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
            var manifest = new jsb.Manifest(customManifestStr*, this._storagePath);
            this._am.loadLocalManifest(manifest, this._storagePath);
            this.progress.string = 'Using custom manifest';
        }
    }*/
    enter (){
        cc.log('进入游戏');
        cc.director.loadScene('main');
    }
    retry () { 
        if (!this._updating && this._canRetry) {
            this._canRetry = false;
            
            this.progress.string = '重试中...';
            this._am.downloadFailedAssets();
        }
    }
    
    checkUpdate () {
        if (this._updating) {
            //this.progress.string = 'Checking or updating ...';
            return;
        }
        if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
            // Resolve md5 url
            var url = this.manifestUrl.nativeUrl;
            if (cc.loader.md5Pipe) {
                url = cc.loader.md5Pipe.transformURL(url);
            }
            this._am.loadLocalManifest(url);
        }
        if (!this._am.getLocalManifest() || !this._am.getLocalManifest().isLoaded()) {
            this.progress.string = '加载本地manifest文件失败.';
            return;
        }
        this._am.setEventCallback(this.checkCb.bind(this));

        this._am.checkUpdate();
        this._updating = true;
    }

    hotUpdate () {
        if (this._am && !this._updating) {
            this._am.setEventCallback(this.updateCb.bind(this));

            if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
                // Resolve md5 url
                var url = this.manifestUrl.nativeUrl;
                if (cc.loader.md5Pipe) {
                    url = cc.loader.md5Pipe.transformURL(url);
                }
                this._am.loadLocalManifest(url);
            }
            let size = (this._am.getTotalBytes() / (1024*1024)).toFixed(2);
            cc.log("总共需要更新--------->"+size)
            if(Number(size) > 5){
                this.showConfirmLayer('检查到您有<color=#0fffff>'+size+'M更新</color>是否更新？',this.onSureButtonClick,this.onCancelButtonClick);
            }else{
                this.startUpdate();
            }
        }
    }
    
    startUpdate (){
        this._failCount = 0;
        // this._am.setDownVersionMd5(Math.ceil(Date.now()/1000/60));
        this._am.update();
        this._updating = true;
    }

    showConfirmLayer (text:string,cb : any,cb2 : any) {
        this.confirmlayer.active = true;
        if(text){
            this.content.string = text;
        }
        this.sureButton.node.off('click');
        this.cancelButton.node.off('click');
        this.sureButton.node.on('click', ()=>{
            this.hideConfirmLayer();
            cb && cb.call(this);
        }, this);
        this.cancelButton.node.on('click', ()=>{
            this.hideConfirmLayer();
            cb2 && cb2.call(this);
        }, this);
    }

    hideConfirmLayer (){
        this.confirmlayer.active = false;
    }

    //确认更新按钮
    onSureButtonClick (){
        this.startUpdate();
    }
    //取消更新按钮
    onCancelButtonClick (){
        this.end();
    }

    //确认重试按钮
    onSureTryButtonClick (){
        this.retry();
    }
    //取消重试按钮
    onCancelTryButtonClick (){
        this.end();
    }

    //确认重试按钮
    onSureFailButtonClick (){
        this.restart();
    }
    //取消重试按钮
    onCancelFailButtonClick (){
        this.end();
    }

    end () {
        //退出游戏
        cc.director.loadScene('main');
        // cc.game.end();
    }

    restart (){
        this.scheduleOnce(() => {
            cc.log('------------重启了')
            // cc.audioEngine.stopAll();
            cc.game.restart();
        },1)
        
    }

    onDestroy () {
        if (this._updateListener) {
            this._am.setEventCallback(null);
            this._updateListener = null;
        }
    }
    /*update (dt:number) {
        this.progressbar.progress += (dt*5)/100;
        this.progress.string = '版本更新中...'+(this.progressbar.progress*100).toFixed(2)+'%';
        this.filesprogress.string = "";
        this.tagimg.node.x = -this.progressbar.totalLength/2+this.progressbar.totalLength*(this.progressbar.progress);
    }*/
}
